package com.example.test_demo.async.another;


import org.apache.ibatis.reflection.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * @program: test_demo
 * @description: 测试并发执行结果  直接启动TestDemoApplication
 * @author: yanghua
 * @create: 2021-09-22 12:15
 * 暂定结论:
 *      通过方法一和方法二的运行结果对比.一只需要7毫秒,二需要4000毫秒.方法体都是沉睡1000毫秒,为啥一快了这么多?
 *          通过控制台日志不难发现运行三个方法使用是三个不同的线程同时进行调用方法的(查询),但是一后面有后缀[Not completed] ,这个后缀
 *          就表明了其实这个方法正处于异步执行中 还没有完成所以执行快
 *
 **/
@Component
public class AnsyGitHubTest implements CommandLineRunner {

    private static final Logger logger = LoggerFactory.getLogger(AnsyGitHubTest.class);

    @Resource
    private final GitHubLookupService gitHubLookupService;

    public AnsyGitHubTest(GitHubLookupService gitHubLookupService) {
        this.gitHubLookupService = gitHubLookupService;
    }

    @Override
    public void run(String... args) throws Exception {
        // Start the clock
        long start = System.currentTimeMillis();


          //方式一
        List<String> list = new ArrayList<>();
        list.add("pivotalsoftware");
        list.add("cloudfoundry");
        list.add("Spring-Projects");
        List<CompletableFuture<CompletableFuture<User>>> futures = list.stream()
                .map(ll -> CompletableFuture.supplyAsync(() -> gitHubLookupService.findUser2(ll), asyncExecutor())
                        .exceptionally(e -> {
                            logger.error("异常: {}", e);
                            //Result failed = Result.failed(e.getMessage());
                            return null;
                        }))
                .collect(Collectors.toList());
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
                .whenComplete((v, th) -> {
                    futures.parallelStream().forEach(f -> {
                        try {
                            logger.info("线程名:{}--> {} " ,Thread.currentThread().getName(), f.get());

                        } catch (InterruptedException e) {

                        } catch (ExecutionException e) {

                        }
                    });
                }).join();





        //=========================================================================

        //方式二
        // Kick of multiple, asynchronous lookups
//        CompletableFuture<User> page1 = gitHubLookupService.findUser("pivotalsoftware");
//        CompletableFuture<User> page2 = gitHubLookupService.findUser("cloudfoundry");
//        CompletableFuture<User> page3 = gitHubLookupService.findUser("Spring-Projects");
//
//        // Wait until they are all done
//        CompletableFuture.allOf(page1,page2,page3).join();
//        logger.info("--> " + page1.get());
//        logger.info("--> " + page2.get());
//        logger.info("--> " + page3.get());
        // Print results, including elapsed time
        logger.info("Elapsed time: " + (System.currentTimeMillis() - start)+"线程名 :"+Thread.currentThread().getName());


    }


    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("yh-");
        executor.initialize();
        return executor;
    }
}
